package edu.uwm.universitydb.controller;

import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;

import edu.uwm.universitydb.framework.exception.DataAccessException;
import edu.uwm.universitydb.model.Person;
import edu.uwm.universitydb.model.Professor;
import edu.uwm.universitydb.model.Project;
import edu.uwm.universitydb.model.Role;
import edu.uwm.universitydb.model.Student;
import edu.uwm.universitydb.model.User;
import edu.uwm.universitydb.service.ServiceFactory;
import edu.uwm.universitydb.service.professor.ProfessorService;
import edu.uwm.universitydb.service.project.ProjectService;
import edu.uwm.universitydb.service.student.StudentService;
import edu.uwm.universitydb.swing.ProjectTableModel;
import edu.uwm.universitydb.view.ProjectMaint;

public class ProjectMaintController implements MouseListener {
	
	public ProjectMaintController(User user) {
		_projectService = ServiceFactory.getInstance().getProjectService();
		
		// Create our associated view
		if (user.getRole().equals(Role.ADMINISTRATOR)) {
			_view = new ProjectMaint(new ProjectTableModel(_projectService), user);
		}
		else {
			ProfessorService prof = ServiceFactory.getInstance().getProfessorService();
			List<Professor> profList = prof.getAllProfessors();
			String prof_ssn = "";
			for (Professor p : profList) {
				//map username to professor firstname
				if (user.getUserName().equals(p.getName().split(" ")[0])) {
					prof_ssn = p.getSsnNum();
					break;
				}
			}
			_view = new ProjectMaint(new ProjectTableModel(_projectService, user, prof_ssn), user);
		}
		
		// Setup our listeners
		_view.getAddButton().addMouseListener(this);
		_view.getEditButton().addMouseListener(this);
		_view.getAddMemberButton().addMouseListener(this);
		_view.getRemoveMemberButton().addMouseListener(this);
		_view.getDelButton().addMouseListener(this);

	}
	
	private void onAddButtonClick() {
		//Dummy values
		int id = 0;
		String sponsor = "";
		String startDate = "";
		String endDate = "";
		int budget = 0;
		Date startdate = null;
		Date enddate = null;
		Professor manage = null;
		//Show Edit User View
		JPanel panel = _view.showNewView();
		boolean validated = false;
		while (!validated) {
			int result = JOptionPane.showConfirmDialog(_view, panel, "Add", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
			if (result == JOptionPane.OK_OPTION) {
				//Get user inputs
				for( Component c : panel.getComponents()) {
					if (ProjectMaint.NAMEFIELD.equals(c.getName())) {
						id = Integer.parseInt(((JTextField)c).getText());
					} 
					else if  (ProjectMaint.SPONSORFIELD.equals(c.getName())) {
						sponsor = ((JTextField)c).getText();
					} 
					else if  (ProjectMaint.STARTDATEFIELD.equals(c.getName())) {
						startDate = ((JTextField)c).getText();
					}
					else if  (ProjectMaint.ENDDATEFIELD.equals(c.getName())) {
						endDate = ((JTextField)c).getText();
					}
					else if  (ProjectMaint.BUDGETFIELD.equals(c.getName())) {
						budget = Integer.parseInt(((JTextField)c).getText());
					} else if  (ProjectMaint.MANAGE.equals(c.getName())) {
						manage = (Professor)(((JComboBox<?>)c).getSelectedItem());
					}
				}
				// Add User
				try {
					startdate = _dateformat.parse(startDate);
					enddate = _dateformat.parse(endDate);
				} catch (ParseException e) {
					JOptionPane.showMessageDialog(_view, "Invalid Date format!");
					continue;
				}
				final Project proj = new Project(id, sponsor, startdate, enddate, budget, null);
				boolean status = false;
				try {
					status = _projectService.createProject(proj, manage);
				} catch (DataAccessException e) {
					JOptionPane.showMessageDialog(_view, e.getMessage());
				}
				if (status == false) {
					JOptionPane.showMessageDialog(_view, "Error adding project!");
				} else {
					validated = true;
				}
			} else {
				//User cancelled add
				break;
			}
			_view.refreshTable();
		}
	}
	
	private void onEditButtonClick() {
		JTable dataTable =  _view.getDataTable();
		//A single row needs to be selected
		int numRows = dataTable.getSelectedRowCount();
		if( numRows == 0 || numRows > 1) {
			JOptionPane.showMessageDialog(_view, "Please select a single row to Edit!");
		} else {
			//Show Edit User View
			int id =  (Integer)dataTable.getValueAt(dataTable.getSelectedRow(), 0);
			Project proj = _projectService.searchProjectByID(id);
			String sponsor =  proj.getSponsor();
			String startDate = "";
			String endDate = "";
			int budget = proj.getBudget();
			Date startdate = null;
			Date enddate = null;
			Professor manage = _projectService.getProjectManager(id);

			//Show Edit User View
			JPanel panel = _view.showMaintView(proj, manage);
			boolean validated = false;
			while (!validated) {
				int result = JOptionPane.showConfirmDialog(_view, panel, "Edit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
				if (result == JOptionPane.OK_OPTION) {
					//Get user inputs
					for( Component c : panel.getComponents()) {
						if (ProjectMaint.NAMEFIELD.equals(c.getName())) {
							id = Integer.parseInt(((JTextField)c).getText());
						} 
						else if  (ProjectMaint.SPONSORFIELD.equals(c.getName())) {
							sponsor = ((JTextField)c).getText();
						} 
						else if  (ProjectMaint.STARTDATEFIELD.equals(c.getName())) {
							startDate = ((JTextField)c).getText();
						}
						else if  (ProjectMaint.ENDDATEFIELD.equals(c.getName())) {
							endDate = ((JTextField)c).getText();
						}
						else if  (ProjectMaint.BUDGETFIELD.equals(c.getName())) {
							budget = Integer.parseInt(((JTextField)c).getText());
						} /*else if  (ProjectMaint.MANAGE.equals(c.getName())) {
							manage = (Professor)(((JComboBox<?>)c).getSelectedItem());
						} editing disabled*/ 
					}
					try {
						startdate = _dateformat.parse(startDate);
						enddate = _dateformat.parse(endDate);
					} catch (ParseException e) {
						JOptionPane.showMessageDialog(_view, "Invalid Date format!");
						continue;
					}
					// Edit User
					boolean status = false;
					Project editProj = new Project(id, sponsor, startdate, enddate, budget, null);
					try {
						status = _projectService.updateProject(editProj);
					} catch (DataAccessException e) {
						JOptionPane.showMessageDialog(_view, e.getMessage());
					}
					if (status == false) {
						JOptionPane.showMessageDialog(_view, "Error editing user!");
					} else {
						validated = true;
					}
				} else {
					//User cancelled edit
					break;
				}
				_view.refreshTable();
			}
			
		}
	} 
	
	private void onAddMemberButtonClick() {
		Person member = null;
		JTable dataTable =  _view.getDataTable();
		//A single row needs to be selected
		int numRows = dataTable.getSelectedRowCount();
		if( numRows == 0 || numRows > 1) {
			JOptionPane.showMessageDialog(_view, "Please select a single row to add members!");
		} else {
			int id =  (Integer)dataTable.getValueAt(dataTable.getSelectedRow(), 0);
			
			// Lets build the list of all professors and students
			ProfessorService prof = ServiceFactory.getInstance().getProfessorService();
			StudentService student = ServiceFactory.getInstance().getStudentService();
			List<Professor> profList = prof.getAllProfessors();
			List<Student> studentList = student.getAllStudents();
			List<Person> canAdd = new ArrayList<Person>(profList);
			canAdd.addAll(studentList);
			
			List<Professor> curProfList = _projectService.getProjectCoinvestigators(id);
			List<Student> curStudentList = _projectService.getProjectStudents(id);
			canAdd.removeAll(curProfList);
			canAdd.removeAll(curStudentList);
			
			//Show Add Member View
			JPanel panel = _view.showMemberView(canAdd);
			boolean validated = false;
			while (!validated) {
				int result = JOptionPane.showConfirmDialog(_view, panel, "Add Member", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
				if (result == JOptionPane.OK_OPTION) {
					//Get user inputs
					for( Component c : panel.getComponents()) {
						if (ProjectMaint.MEMBER.equals(c.getName())) {
							member = (Person)(((JComboBox<?>)c).getSelectedItem());
						}
					}
					
					Project proj = _projectService.searchProjectByID(id);
					boolean status = false;
					if (member instanceof Professor) {
						status = _projectService.associateCoInvestigator(member.getSsnNum(), proj.getProjectNum());
					}
					else if (member instanceof Student) {
						status = _projectService.associateProjectWithStudent(member.getSsnNum(), proj.getProjectNum());
					}
					if (status == false) {
						JOptionPane.showMessageDialog(_view, "Error adding member to project");
					} else {
						validated = true;
					}
				} else {
					//User cancelled edit
					break;
				}
			}
		}
	}
	
	private void onRemoveMemberButtonClick() {
		Person member = null;
		JTable dataTable =  _view.getDataTable();
		//A single row needs to be selected
		int numRows = dataTable.getSelectedRowCount();
		if( numRows == 0 || numRows > 1) {
			JOptionPane.showMessageDialog(_view, "Please select a single row to remove members!");
		} else {
			//Get the associated project selected
			int id =  (Integer)dataTable.getValueAt(dataTable.getSelectedRow(), 0);
			Project proj = _projectService.searchProjectByID(id);
			
			List<Professor> profList = _projectService.getProjectCoinvestigators(id);
			List<Student> studentList = _projectService.getProjectStudents(id);
			
			List<Person> combined = new ArrayList<Person>(profList);
			combined.addAll(studentList);
			
			//Show Add Member View
			JPanel panel = _view.showMemberView(combined);
			boolean validated = false;
			while (!validated) {
				int result = JOptionPane.showConfirmDialog(_view, panel, "Edit Member", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
				if (result == JOptionPane.OK_OPTION) {
					//Get user inputs
					for( Component c : panel.getComponents()) {
						if (ProjectMaint.MEMBER.equals(c.getName())) {
							member = (Person)(((JComboBox<?>)c).getSelectedItem());
						}
					}
					boolean status = false;
					if (member instanceof Professor) {
						status = _projectService.removeCoInvestigator(member.getSsnNum(), proj.getProjectNum());
					}
					else if (member instanceof Student) {
						status = _projectService.removeStudentFromProject(member.getSsnNum(), proj.getProjectNum());
					}
					if (status == false) {
						JOptionPane.showMessageDialog(_view, "Error removing member to project");
					} else {
						validated = true;
					}
				} else {
					//User cancelled edit
					break;
				}
			}
		}
	}
	
	private void onDelButtonClick() {
		JTable dataTable = _view.getDataTable();
		int numRows = dataTable.getSelectedRowCount();
		
		//At least 1 row needs to be selected
		if (numRows == 0) {
			JOptionPane.showMessageDialog(_view, "Please select row/s to Delete!");
		} else {
			//Confirm delete
			int confirm = JOptionPane.showConfirmDialog(_view,
					"Are you sure you want to delete?", "Confirm", JOptionPane.YES_NO_OPTION);
			if (confirm == JOptionPane.YES_OPTION) {
				List<Integer> selectedKeys = new ArrayList<Integer>();
				boolean status = true;
				for (int i : dataTable.getSelectedRows()) {
					int keyVal = (Integer)dataTable.getValueAt(i, 0);
					selectedKeys.add(keyVal);
				}
				//Perform Delete
				for (Integer key : selectedKeys) {
					status = _projectService.removeProject(key);
					if (status == false) {
						JOptionPane.showMessageDialog(_view, "Internal error deleting user!");
						break;
					}
				}
				dataTable.clearSelection();
				_view.refreshTable();
			}
		}
	}
	
	public ProjectMaint getView() {
		return _view;
	}
	
	
	@Override
	public void mouseClicked(MouseEvent e) {
		//Based on the element clicked, fire off appropriate handler method.
		switch(e.getComponent().getName()) {
			case ProjectMaint.EDITBUTTON: 
				this.onEditButtonClick();
				break;
			case ProjectMaint.ADDMEMBERBUTTON:
				this.onAddMemberButtonClick();
				break;
			case ProjectMaint.REMOVEMEMBERBUTTON:
				this.onRemoveMemberButtonClick();
				break;
			case ProjectMaint.DELBUTTON: 
				this.onDelButtonClick();
				break;
			case ProjectMaint.ADDBUTTON: 
				this.onAddButtonClick();
				break;
			default: 
				//Not sure what they clicked, do nothing
				break;
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// Unused		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// Unused
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// Unused
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// Unused
	}	
	
	private final DateFormat _dateformat = new SimpleDateFormat("yyyy-MM-dd");

	private ProjectMaint _view;
	
	private ProjectService _projectService;
	
	public static final String ID = "ProjectMnt";
}
